﻿using JESAI.Core.Json;
using JESAI.Core.Util.Extensions;
using JESAI.Core.Util.Helpers;
using JESAI.Core.Util.Parameters.Formats;
using System;
using System.Collections.Generic;
using System.Linq;

namespace JESAI.Core.Util.Parameters
{

    /// <summary>
    /// 参数生成器
    /// </summary>
    public class ParameterBuilder : IParameterManager
    {
        /// <summary>
        /// 参数字典
        /// </summary>
        private readonly IDictionary<string, object> _params;

        /// <summary>
        /// 初始化一个<see cref="ParameterBuilder"/>类型的实例
        /// </summary>
        public ParameterBuilder() => _params = new Dictionary<string, object>();

        /// <summary>
        /// 初始化一个<see cref="ParameterBuilder"/>类型的实例
        /// </summary>
        /// <param name="builder">参数生成器</param>
        public ParameterBuilder(ParameterBuilder builder) : this(builder.GetDictionary())
        {
        }

        /// <summary>
        /// 初始化一个<see cref="ParameterBuilder"/>类型的实例
        /// </summary>
        /// <param name="dictionary">字典</param>
        public ParameterBuilder(IDictionary<string, object> dictionary)
        {
            _params = dictionary == null
                ? new Dictionary<string, object>()
                : new Dictionary<string, object>(dictionary);
        }

        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="name">参数名</param>
        public object this[string name]
        {
            get => GetValue(name);
            set => Add(name, value);
        }

        /// <summary>
        /// 是否空参数
        /// </summary>
        public bool IsEmpty => _params.Count == 0;

        /// <summary>
        /// 添加参数，如果参数已存在则替换
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public ParameterBuilder Add(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                return this;
            value = GetValue(value);
            if (string.IsNullOrWhiteSpace(value.SafeString()))
                return this;
            key = key.Trim();
            if (_params.ContainsKey(key))
                _params[key] = value;
            else
                _params.Add(key, value);
            return this;
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="value">值</param>
        private string GetValue(object value)
        {
            if (value == null)
                return null;
            if (value is DateTime dateTime)
                return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
            if (value is bool boolValue)
                return boolValue.ToString().ToLower();
            if (value is decimal)
                return value.SafeString();
            return value.SafeString();
        }

        /// <summary>
        /// 获取字典
        /// </summary>
        /// <param name="isSort">是否按参数名排序</param>
        /// <param name="isUrlEncode">是否Url编码</param>
        /// <param name="encoding">字符编码，默认值：UTF-8</param>
        public IDictionary<string, object> GetDictionary(bool isSort = true, bool isUrlEncode = false,
            string encoding = "UTF-8")
        {
            var result = _params.ToDictionary(t => t.Key, t => GetEncodeValue(t.Value, isUrlEncode, encoding));
            if (isSort == false)
                return result;
            return new SortedDictionary<string, object>(result);
        }

        /// <summary>
        /// 获取编码的值
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="isUrlEncode">是否Url编码</param>
        /// <param name="encoding">字符编码</param>
        private object GetEncodeValue(object value, bool isUrlEncode, string encoding)
        {
            if (isUrlEncode)
                return Url.UrlEncode(value.SafeString(), encoding);
            return value;
        }

        /// <summary>
        /// 获取键值对集合
        /// </summary>
        public IEnumerable<KeyValuePair<string, object>> GetKeyValuePairs() => _params;

        /// <summary>
        /// 清空
        /// </summary>
        public void Clear() => _params.Clear();

        /// <summary>
        /// 移除参数
        /// </summary>
        /// <param name="key">键</param>
        public bool Remove(string key) => _params.Remove(key);

        /// <summary>
        /// 转换为Json
        /// </summary>
        /// <param name="isConvertToSingleQuotes">是否将双引号转成单引号</param>
        public string ToJson(bool isConvertToSingleQuotes = false) => JsonHelper.ToJson(_params, isConvertToSingleQuotes);

        /// <summary>
        /// 获取结果
        /// </summary>
        /// <param name="format">参数格式化器</param>
        /// <param name="isSort">是否按参数名排序</param>
        /// <param name="isUrlEncode">是否Url编码</param>
        /// <param name="encoding">字符编码，默认值：UTF-8</param>
        public string Result(IParameterFormat format, bool isSort = false, bool isUrlEncode = false,
            string encoding = "UTF-8")
        {
            if (format == null)
                throw new ArgumentNullException(nameof(format));
            var result = string.Empty;
            foreach (var param in GetDictionary(isSort, isUrlEncode, encoding))
                result = format.Join(result, format.Format(param.Key, param.Value));
            return result;
        }

        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="name">参数名</param>
        public object GetValue(string name)
        {
            if (name.IsEmpty())
                return string.Empty;
            if (_params.ContainsKey(name))
                return _params[name];
            return string.Empty;
        }
    }
}